package com.immediatus.util;

import com.immediatus.engine.contracts.IMatcher;
import com.immediatus.engine.util.ParameterCallable;

import java.util.ArrayList;

public class SmartList<T> extends ArrayList<T>{

    public SmartList(){
    }

    public SmartList(final int capacity_){
        super(capacity_);
    }

    public boolean remove(final T item_, final ParameterCallable<T> parameterCallable_){
        final boolean removed = this.remove(item_);
        if (removed){
            parameterCallable_.call(item_);
        }
        return removed;
    }

    public T remove(final IMatcher<T> matcher_){
        for (int i = 0; i < this.size(); i++){
            if (matcher_.matches(this.get(i))){
                return this.remove(i);
            }
        }
        return null;
    }

    public T remove(final IMatcher<T> matcher_, final ParameterCallable<T> parameterCallable_){
        for (int i = this.size() - 1; i >= 0; i--){
            if (matcher_.matches(this.get(i))){
                final T removed = this.remove(i);
                parameterCallable_.call(removed);
                return removed;
            }
        }
        return null;
    }

    public boolean removeAll(final IMatcher<T> matcher_){
        boolean result = false;
        for (int i = this.size() - 1; i >= 0; i--){
            if (matcher_.matches(this.get(i))){
                this.remove(i);
                result = true;
            }
        }
        return result;
    }

    public boolean removeAll(final IMatcher<T> matcher_, final ParameterCallable<T> parameterCallable_){
        boolean result = false;
        for (int i = this.size() - 1; i >= 0; i--){
            if (matcher_.matches(this.get(i))){
                final T removed = this.remove(i);
                parameterCallable_.call(removed);
                result = true;
            }
        }
        return result;
    }

    public void clear(final ParameterCallable<T> parameterCallable_){
        for (int i = this.size() - 1; i >= 0; i--){
            final T removed = this.remove(i);
            parameterCallable_.call(removed);
        }
    }

    public T find(final IMatcher<T> matcher_){
        for (int i = this.size() - 1; i >= 0; i--){
            final T item = this.get(i);
            if (matcher_.matches(item)){
                return item;
            }
        }
        return null;
    }

    public void call(final ParameterCallable<T> parameterCallable_){
        for (int i = this.size() - 1; i >= 0; i--){
            final T item = this.get(i);
            parameterCallable_.call(item);
        }
    }

    public void call(final IMatcher<T> matcher_, final ParameterCallable<T> parameterCallable_){
        for (int i = this.size() - 1; i >= 0; i--){
            final T item = this.get(i);
            if (matcher_.matches(item)){
                parameterCallable_.call(item);
            }
        }
    }
}
